package my.ssm.ioc;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

/**
 * @author zhupanlin
 * @version 1.0
 * @description: TODO
 * @date 2023/10/19 16:36
 */
public class ClassPathXmlApplicationContext implements BeanFactory {

    private Map<String, Object> beanMap = new HashMap<>();

    public ClassPathXmlApplicationContext() throws ParserConfigurationException, ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
        ThreadLocal<?> threadLocal = new ThreadLocal<>();
        InputStream inputStream = getClass().getClassLoader().getResourceAsStream("applicationContext.xml");
        // 1. 创建DocumentBuilderFactory
        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
        // 2. 创建DocumentBuilder对象
        DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
        // 3. 创建Document对象
        Document document = documentBuilder.newDocument();
        // 4. 获取所有的bean节点
        NodeList beanNodeList = document.getElementsByTagName("bean");
        for (int i = 0; i < beanNodeList.getLength(); ++i) {
            Node beanNode = beanNodeList.item(i);
            if (beanNode.getNodeType() == Node.ELEMENT_NODE){
                Element beanElement = (Element)beanNode;
                String beanId = beanElement.getAttribute("id");
                String className = beanElement.getAttribute("class");
                Class<?> beanClass = Class.forName(className);
                // 创建bean实例
                Object beanObj = beanClass.newInstance();
                // 将bean实例对象保存到map容器
                beanMap.put(beanId, beanObj);
                // bean和bean之间的依赖关系
            }
        }
        // 5. 组装bean之间的依赖关系
        // 自动装配
        for (int i = 0; i < beanNodeList.getLength(); ++i) {
            Node beanNode = beanNodeList.item(i);
            if (beanNode.getNodeType() == Node.ELEMENT_NODE){
                Element beanElement = (Element) beanNode;
                String beanId = beanElement.getAttribute("id");
                NodeList beanChildNodesList = beanElement.getChildNodes();
                for (int j = 0; j < beanChildNodesList.getLength(); ++j){
                    Node beanChildNode = beanChildNodesList.item(j);
                    if (beanChildNode.getNodeType() == Node.ELEMENT_NODE && "property".equals(beanChildNode.getNodeName())){
                        Element propertyElement = (Element) beanChildNode;
                        String propertyName = propertyElement.getAttribute("name");
                        String propertyRef = propertyElement.getAttribute("ref");
                        // 1) 找到propertyRef对应的实例
                        Object refObj = beanMap.get(beanId);
                        Object beanObj = beanMap.get(beanId);
                        Class<?> beanClazz = beanObj.getClass();
                        Field propertyField = beanClazz.getDeclaredField("propertyName");
                        propertyField.setAccessible(true);
                        propertyField.set(beanObj, refObj);
                    }
                }
            }
        }
    }

    @Override
    public Object getBean(String id) {
        return beanMap.get(id);
    }
}
